const VERTEX_SHADER_SOURCE = `#version 300 es
  layout(location=0) in vec4 a_Position;
  layout(location=1) in vec2 a_TexCoord;
  out vec2 v_TexCoord;
  void main() {
    gl_Position = a_Position;
    v_TexCoord = a_TexCoord;
  }
`;

const FRAGMENT_SHADER_SOURCE = `#version 300 es
  precision mediump float;
  out vec4 outColor;
  uniform sampler2D u_Sampler;
  in vec2 v_TexCoord;
  void main() {
    outColor = texture(u_Sampler, v_TexCoord);
  }
`;

const main = () => {
  /** @type { WebGL2RenderingContext } */
  const gl = setupWebgl(document.querySelector("#root"));
  initShaders(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE);

  let n = initVertexBuffers(gl);
  if (n < 0) {
    console.error("Failed to set the positions of vertices.");
    return;
  }

  initTextures(gl, n);
};

const initVertexBuffers = (gl) => {
  // prettier-ignore
  let vertices = new Float32Array([
    -0.5, 0.5, 0.0, 1.0,
    -0.5, -0.5, 0.0, 0.0,
    0.5, 0.5, 1.0, 1.0,
    0.5, -0.5, 1.0, 0.0
  ]);
  let n = 4;
  // 创建缓冲区对象
  let vertexBuffer = gl.createBuffer();

  if (!vertexBuffer) {
    console.error("Failed to create the buffer object.");
    return -1;
  }

  const FSIZE = vertices.BYTES_PER_ELEMENT;
  // 将缓冲区对象绑定到目标
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  // 向缓冲区对象写入数据
  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

  // 讲当前缓冲区的数据分配给a_Position
  gl.vertexAttribPointer(0, 2, gl.FLOAT, false, FSIZE * 4, 0);
  // 开启定点着色器访问缓冲区数据
  gl.enableVertexAttribArray(0);

  gl.vertexAttribPointer(1, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);
  gl.enableVertexAttribArray(1);
  return n;
};

const initTextures = (gl, n) => {
  let texture = gl.createTexture();
  let u_Sampler = gl.getUniformLocation(gl.program, "u_Sampler");
  let image = new Image();
  image.addEventListener("load", (e) => {
    loadTexture(gl, n, texture, u_Sampler, image);
  });
  image.src = "../resource/sky.jpg";
  return true;
};

const loadTexture = (gl, n, texture, u_Sampler, image) => {
  // 影像坐标系 x→+   y↓+
  // webgl 坐标系 y↑+ x→+
  // 先将y轴翻转后，才能将图像映射到坐标系内
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
  gl.activeTexture(gl.TEXTURE0);
  gl.bindTexture(gl.TEXTURE_2D, texture);

  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);

  gl.uniform1i(u_Sampler, 0);

  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
};
